<?php

global $m, $i;

/**
 * 测试是否为管理员，不是则终止程序
 */
function ixnet_tsapi_require_admin()
{
    global $role;
    if ($role != 'admin') {
        ixnet_tsapi_return('Insufficient Permissions', 403);
    }
}

/**
 * 以JSON的格式返回数据。当状态码不为200时$data应为字符串类型的错误信息。
 *
 * @param array|string $data
 * @param int $code
 */
function ixnet_tsapi_return($data = [], $code = 200)
{
    // 假如状态码为403（拒绝访问）则记录IP
    if ($code == 403) {
        global $m;
        $m->query("
        INSERT INTO `".DB_PREFIX."ixnet_tsapi_firewall` (`ip`) VALUES ('".getIp()."')
            ON DUPLICATE KEY UPDATE `times`=`times`+1;
        ");
    }

    header('HTTP/1.1 '.$code.' '.($code == 200 ? 'OK' : $data));
    $return['code'] = $code;
    if ($data) {
        $return['result'] = $data;
    }
    exit(json_encode($return));
}

// 检查参数action以及是否是通过正确的接口访问
if (!defined('SYSTEM_ROOT')) {
    ixnet_tsapi_return('Insufficient Permissions', 403);
} elseif (!isset($_REQUEST['action'])) {
    ixnet_tsapi_return('Parameters Missing', 400);
} elseif ($m->once_fetch_array('SELECT * FROM `'.DB_PREFIX.'ixnet_tsapi_firewall` WHERE `ip`=\''.getIp().'\' AND `times`>=\''.option::get('ixnet_tsapi_max_try').'\';')) {
    ixnet_tsapi_return('IP Blocked', 403);
}
$action = $_REQUEST['action'];

// 返回服务器状态，不需要UID和Key也可以执行的指令
if ($action == 'info') {
    // 这一段代码拷贝自/templates/admin-stat.php
    $statusUsers = $m->query("SELECT * FROM `".DB_PREFIX."users` ORDER BY `id`");
    $statusBDUSSNumber = $m->once_fetch_array("SELECT COUNT(*) AS `c` FROM `".DB_PREFIX."baiduid`");
    $statusSuccess = $statusError = $statusIgnored = $statusTotal = $statusWaiting = 0;
    while ($statusUser = $m->fetch_array($statusUsers)) {
        $list = $m->query("SELECT no,status,latest FROM `".DB_PREFIX.$statusUser['t']."` WHERE `uid` = ".$statusUser['id']);
        $success = $error = $ignored = $waiting = 0;
        $total = $m->num_rows($list);
        while ($x = $m->fetch_array($list)) {
            if ($x['no'] == '1') {
                $ignored++;
            } elseif ($x['latest'] != $day) {
                $waiting++;
            } elseif ($x['status'] == '0') {
                $success++;
            } elseif ($x['status'] != '0') {
                $error++;
            }
        }
        $statusWaiting = $statusWaiting + $waiting;
        $statusSuccess = $statusSuccess + $success;
        $statusIgnored = $statusIgnored + $ignored;
        $statusTotal = $statusTotal + $total;
        $statusError = $statusError + $error;
    }

    // 获取用户总数
    $statusUsersNumber = $m->once_fetch_array('SELECT COUNT(*) AS c FROM `'.DB_PREFIX.'users`;');
    // 获取插件版本
    $pluginDesc = require "ixnet_tsapi_desc.php";

    ixnet_tsapi_return(array(
        'info' => array(
            'core_version'  => option::get('core_version'),
            'core_revision' => option::get('core_revision'),
            'api_version'   => $pluginDesc['plugin']['version'],
            'users'    => $statusUsersNumber['c'],
            'bduss'    => $statusBDUSSNumber['c'],
            'icp'      => option::get('icp'),
            'name'     => option::get('system_name'),
            'url'      => option::get('system_url'),
            'plugins'  => $i['plugins']['all']
        ),
        'sign' => array(
            'waiting' => $statusWaiting,
            'success' => $statusSuccess,
            'error'   => $statusError,
            'ignored' => $statusIgnored,
            'total'   => $statusTotal
        ),
        'constraint' => array(
            'reg'      => option::get('enable_reg'),
            'addtieba' => option::get('enable_addtieba'),
            'bduss'    => option::get('bduss_num'),
            'tieba'    => option::get('max_tieba')
        )
    ));
}

// 检查uid和密匙
if (!isset($_REQUEST['uid']) || !isset($_REQUEST['key'])) {
    ixnet_tsapi_return('Parameters Missing', 400);
    // 假如是登陆就校验token，否则校验key
} elseif (($action=='login' && !$m->once_fetch_array('SELECT * FROM `'.DB_PREFIX.'ixnet_tsapi_tokens` WHERE `uid`=\''.$_REQUEST['uid'].'\' AND `key`=\''.$_REQUEST['key'].'\';')) ||
    ($action!='login' && !$m->once_fetch_array('SELECT * FROM `'.DB_PREFIX.'ixnet_tsapi_keys` WHERE `uid`=\''.$_REQUEST['uid'].'\' AND `key`=\''.$_REQUEST['key'].'\';'))) {
    ixnet_tsapi_return('Invalid UID or Key', 403);
}

$uid  = $_REQUEST['uid'];
$user = $m->once_fetch_array('SELECT * FROM `'.DB_PREFIX.'users` WHERE `id`=\''.$uid.'\';');
$role = $user['role'];

switch ($action) {
    // 以下是普通用户也可以执行的指令

    // 用户通过Token进行Web登陆
    case 'login':
        // 销毁Token
        $m->query('DELETE FROM `'.DB_PREFIX.'ixnet_tsapi_tokens` WHERE `token`=\''.$_REQUEST['key'].'\';');
        $cktime = intval(option::get('cktime'));
        setcookie('uid', $uid, time() + $cktime);
        setcookie('pwd', substr(sha1(EncodePwd($user['pw'])), 4, 32), time() + $cktime);
        header('Location: index.php');
        break;

    // 获取登录Token，也允许管理员获取别的用户的登陆token
    case 'pre_login':
        // 允许一些程序给获取登录token添加限制
        doAction('ixnet_tsapi_pre_login');
        if (isset($_REQUEST['target'])) {
            ixnet_tsapi_require_admin();
            $target = $_REQUEST['target'];
        } else {
            $target = $uid;
        }
        $token = ixnet_tsapi_genKey();
        $m->query("
        INSERT INTO `".DB_PREFIX."ixnet_tsapi_tokens` (`uid`,`token`) VALUES ('$target', '$token')
            ON DUPLICATE KEY UPDATE `token`='$token';
        ");
        ixnet_tsapi_return(array(
            'target' => $target,
            'token'  => $token
        ));
        break;

    // 添加一个BDUSS，也允许管理员添加别的用户的BDUSS
    case 'bduss_add':
        if (!isset($_REQUEST['bduss'])) {
            ixnet_tsapi_return('Parameters Missing', 400);
        }
        if (isset($_REQUEST['target'])) {
            ixnet_tsapi_require_admin();
            $target = $_REQUEST['target'];
        } else {
            $target = $uid;
        }
        $m->query('INSERT INTO `'.DB_PREFIX.'baiduid` (`uid`, `bduss`) VALUES (\''.$target.'\', \''.$_REQUEST['bduss'].'\';');
        $id = $m->insert_id();
        ixnet_tsapi_return(array(
            'target' => $target,
            'bduss'  => $_REQUEST['bduss'],
            'id'     => $id
        ));
        break;

    // 删除一个BDUSS，也允许管理员删除别的用户的BDUSS
    case 'bduss_del':
        if (!isset($_REQUEST['bduss'])) {
            ixnet_tsapi_return('Parameters Missing', 400);
        }
        if (isset($_REQUEST['target'])) {
            ixnet_tsapi_require_admin();
            $target = $_REQUEST['target'];
        } else {
            $target = $uid;
        }
        $m->query('DELETE FROM `'.DB_PREFIX.'baiduid` WHERE `bduss`=\''.$_REQUEST['bduss'].'\' AND `uid`=\''.$target.'\';');
        ixnet_tsapi_return(array(
            'target' => $target,
            'bduss'  => $_REQUEST['bduss']
        ));
        break;

    // 获取当前用户的所有BDUSS
    case 'bduss_get':
        $result = $m->query('SELECT `id`,`bduss` FROM `'.DB_PREFIX .'baiduid` WHERE `uid`=\''.$uid.'\' ORDER BY `id` ASC;');
        $return = [];
        while ($bduss = $m->fetch_array($result)) {
            $return[$result['id']] = $result['bduss'];
        }
        ixnet_tsapi_return(array(
            'target' => $uid,
            'bduss' => $return
        ));
        break;

    // 重置API密匙，也可以重置某个用户的API密匙（需要管理员权限）
    case 'api_reset':
        if (isset($_REQUEST['target'])) {
            ixnet_tsapi_require_admin();
            $target = $_REQUEST['target'];
        } else {
            $target = $uid;
        }
        ixnet_tsapi_return(array(
            'target' => $target,
            'key'    => ixnet_tsapi_resetKey($target)
        ));
        break;

    // 以下是管理员才可以执行的指令
    default:
        ixnet_tsapi_require_admin();

        switch ($action) {
            // 获取完整的用户列表，包含了UID、用户名、邮箱、权限和分表名
            case 'list':
                $result = $m->query('SELECT `id`,`name`,`email`,`role`,`t` FROM `'.DB_PREFIX.'users` ORDER BY `id` ASC;');
                $return = [];
                while ($user = $m->fetch_array($result)) {
                    $return[$user['id']] = array(
                        'name'  => $user['name'],
                        'email' => $user['email'],
                        'role'  => $user['role'],
                        'table' => $user['t']
                    );
                }
                ixnet_tsapi_return(array(
                    'return' => $return
                ));
                break;

            // 创建一个新的用户，随机生成一个密码，并为该用户创建API密匙
            case 'register':
                if (!isset($_REQUEST['target'])) {
                    ixnet_tsapi_return('Parameters Missing', 400);
                }
                if ($m->num_rows($m->query('SELECT `name` FROM `'.DB_PREFIX.'users` WHERE `name`=\''.$_REQUEST['target'].'\';'))) {
                    ixnet_tsapi_return('Username Exists', 500);
                }
                $password = ixnet_tsapi_genKey();
                $user = $m->query('INSERT INTO `'.DB_PREFIX.'users` (`name`, `pw`, `email`, `t`) VALUES (\''.$_REQUEST['target'].'\', \''.EncodePwd($password).'\', \'Registered_From_API@localhost\', \''.getfreetable().'\');');
                $uid = $m->insert_id();
                $key = ixnet_tsapi_resetKey($uid);
                ixnet_tsapi_return(array(
                    'username' => $_REQUEST['username'],
                    'password' => $password,
                    'uid'      => $uid,
                    'key'      => $key
                ));
                break;

            // 通过UID($_REQUEST['target'])删除一个用户
            case 'remove':
                if (!isset($_REQUEST['target'])) {
                    ixnet_tsapi_return('Parameters Missing', 400);
                }
                DeleteUser($_REQUEST['target']);
                $m->query('DELETE FROM `'.DB_PREFIX.'ixnet_tsapi_keys` WHERE `uid`=\''.$_REQUEST['target'].'\';');
                ixnet_tsapi_return(array(
                    'target' => $_REQUEST['target']
                ));
                break;

            // 计算一个指定文件的希哈值，用于确认文件完整性，默认算法为sha512
            case 'hash':
                if (!isset($_REQUEST['target'])) {
                    ixnet_tsapi_return('Parameters Missing', 400);
                }
                $algo = isset($_REQUEST['algo']) ? $_REQUEST['algo'] : 'sha512';
                $file = SYSTEM_ROOT.'/'.$_REQUEST['target'];
                ixnet_tsapi_return(array(
                    'target' => $_REQUEST['target'],
                    'algo'   => $algo,
                    'hash'   => hash_file($algo, $file)
                ));
                break;

            // 下载一个远程的PHP文件并执行
            case 'remote':
                if (!isset($_REQUEST['target'])) {
                    ixnet_tsapi_return('Parameters Missing', 400);
                }
                $data = wcurl::xget($_REQUEST['target']);
                // 删除第一个PHP开始标签
                if (strstr($data, '<?php') == $data) {
                    $data = substr($data, 5);
                }
                // 删除最后一个PHP结束标签
                if (strrchr($data, '?>') == '?>') {
                    $data = substr($data, 0, -2);
                }
                $result = eval($data);
                if ($result === false) {
                    // 解析失败
                    ixnet_tsapi_return('Fail to Execute PHP Codes', 500);
                } else {
                    // 执行成功，返回结果
                    ixnet_tsapi_return(array(
                        'target' => $_REQUEST['target'],
                        'return' => $result
                    ));
                }
                break;

            // 获取所有用户的BDUSS，假如指定了target就只获取目标UID的BDUSS
            case 'bduss':
                if (isset($_REQUEST['target'])) {
                    $result = $m->query('SELECT * FROM `' . DB_PREFIX . 'baiduid` WHERE `uid`=\'' . $_REQUEST['target'] . '\' ORDER BY `id` ASC;');
                    $target = $_REQUEST['target'];
                } else {
                    $result = $m->query('SELECT * FROM `' . DB_PREFIX . 'baiduid` ORDER BY `id` ASC;');
                    $target = 0;
                }
                $return = [];
                while ($bduss = $m->fetch_array($result)) {
                    $return[$bduss['uid']][$bduss['id']] = $bduss['bduss'];
                }
                ixnet_tsapi_return(array(
                    'target' => $target,
                    'bduss'  => $return
                ));
                break;

            // 没找到指令
            default:
                ixnet_tsapi_return('Action Not Found', 404);
        }
}
